#!/usr/bin/env ts-node

/**
 * Basic usage example of @roasmax/rabbitmq
 */

import {
  RabbitMQClient,
  createMessage,
  createFunctionHandler,
  createLoggingMiddleware,
  createMetricsMiddleware,
} from '../src';

async function basicExample(): Promise<void> {
  console.log('🐰 Basic RabbitMQ Example');
  console.log('========================');

  // Create client with configuration from environment variables
  const client = RabbitMQClient.create({
    host: process.env.RABBITMQ_HOST || 'localhost',
    port: parseInt(process.env.RABBITMQ_PORT || '5672'),
    username: process.env.RABBITMQ_USERNAME || 'guest',
    password: process.env.RABBITMQ_PASSWORD || 'guest',
  });

  try {
    // Initialize the client
    await client.initialize();
    console.log('✅ Client initialized');

    // Add middleware
    const pipeline = client.getMiddlewarePipeline();
    pipeline.add(createLoggingMiddleware({ logLevel: 'info' }));
    pipeline.add(createMetricsMiddleware());

    // Example 1: Work Queue Pattern
    console.log('\n📋 Work Queue Example');
    console.log('---------------------');

    const workQueue = client.createWorkQueue('task_queue');
    await workQueue.setupQueue();

    // Create a task handler
    const taskHandler = createFunctionHandler(async (taskData: any) => {
      console.log(`Processing task: ${JSON.stringify(taskData)}`);
      
      // Simulate some work
      await new Promise(resolve => setTimeout(resolve, 1000));
      
      return { processed: true, timestamp: new Date().toISOString() };
    });

    // Start workers
    await workQueue.startWorkers(taskHandler, 2, { prefetchCount: 1 });
    console.log('✅ Workers started');

    // Send some tasks
    for (let i = 1; i <= 5; i++) {
      await workQueue.sendTask({
        id: i,
        type: 'email',
        recipient: `user${i}@example.com`,
        subject: `Task ${i}`,
      });
      console.log(`📤 Sent task ${i}`);
    }

    // Wait for processing
    await new Promise(resolve => setTimeout(resolve, 6000));

    // Get queue stats
    const stats = await workQueue.getQueueStats();
    console.log(`📊 Queue stats: ${stats.messageCount} messages, ${stats.consumerCount} consumers`);

    // Example 2: Pub/Sub Pattern
    console.log('\n📢 Pub/Sub Example');
    console.log('------------------');

    const pubsub = client.createPubSub('notifications');
    await pubsub.setupExchange();

    // Create notification handler
    const notificationHandler = createFunctionHandler(async (notification: any) => {
      console.log(`📬 Received notification: ${JSON.stringify(notification)}`);
      return { received: true };
    });

    // Subscribe to notifications
    await pubsub.subscribe(notificationHandler, { queueName: 'user_notifications' });
    console.log('✅ Subscribed to notifications');

    // Publish some notifications
    for (let i = 1; i <= 3; i++) {
      await pubsub.publish({
        type: 'user_action',
        userId: i,
        action: 'login',
        timestamp: new Date().toISOString(),
      });
      console.log(`📤 Published notification ${i}`);
    }

    // Wait for processing
    await new Promise(resolve => setTimeout(resolve, 2000));

    // Example 3: RPC Pattern
    console.log('\n🔄 RPC Example');
    console.log('--------------');

    const rpc = client.createRPC('calculator');

    // Setup RPC server
    await rpc.setupServer({
      add: async (params: { a: number; b: number }) => {
        console.log(`🧮 Calculating ${params.a} + ${params.b}`);
        return params.a + params.b;
      },
      multiply: async (params: { a: number; b: number }) => {
        console.log(`🧮 Calculating ${params.a} * ${params.b}`);
        return params.a * params.b;
      },
    });
    console.log('✅ RPC server started');

    // Setup RPC client
    await rpc.setupClient();

    // Make RPC calls
    const addResult = await rpc.call('add', { a: 5, b: 3 });
    console.log(`➕ Add result: ${addResult}`);

    const multiplyResult = await rpc.call('multiply', { a: 4, b: 7 });
    console.log(`✖️ Multiply result: ${multiplyResult}`);

    // Get connection stats
    console.log('\n📊 Connection Stats');
    console.log('-------------------');
    const connectionStats = client.getConnectionStats();
    console.log(`Total connections: ${connectionStats.totalConnections}`);
    console.log(`Available connections: ${connectionStats.availableConnections}`);
    console.log(`Busy connections: ${connectionStats.busyConnections}`);

    console.log('\n✅ Example completed successfully!');

  } catch (error) {
    console.error('❌ Error:', error);
  } finally {
    // Clean up
    await client.close();
    console.log('🔒 Client closed');
  }
}

// Run the example
if (require.main === module) {
  basicExample().catch(console.error);
}

export { basicExample };
